<template>
	<div style="width: 60%; min-height: 600px; margin: 20px auto">
		<div style="margin-top: 20px" v-if="data.tableData?.length !== 0">
			<div style="display: flex; align-items: center; gap: 20px; margin-bottom: 10px"
				v-for="item in data.tableData" :key="item.id" class="card">
				<img alt="" :src="item.friendAvatar" style="width: 60px; height: 60px; border-radius: 50%" />
				<div style="font-size: 18px"><span style="color: #666666">名称：</span>{{ item.friendName }}</div>
				<div style="font-size: 18px"><span style="color: #666666">账号：</span>{{ item.friendUserName }}</div>

				<div style="flex: 1; text-align: right">
					<el-button type="primary" round @click="showPublicKey(item)">发送公钥</el-button>
					<el-button v-if="1==item.isShowPublicKey" type="primary" round
						@click="getPublicKey(item)">下载公钥</el-button>
					<el-button type="primary" round @click="showFriendApply(item)">发送文件</el-button>
				</div>

			</div>
		</div>
		<div style="margin-top: 20px" v-else>
			<div class="card" style="font-size: 24px; color: #8c939d">......未找到账号为该找的用户</div>
		</div>

		<!-- 公钥显示对话框 -->
		<el-dialog v-model="data.publicKeyVisible" title="公钥信息" width="40%" destroy-on-close>
			<div v-if="data.selectedPublicKey">
				<pre>{{ data.selectedPublicKey }}</pre>
			</div>
			<div v-else>
				<p>正在加载公钥...</p>
			</div>
			<template #footer>
				<span class="dialog-footer">
					<el-button @click="data.publicKeyVisible = false">关闭</el-button>
				</span>
			</template>
		</el-dialog>

		<!-- 分享文件信息对话框 -->
		<el-dialog v-model="data.formVisible" title="分享文件信息" width="40%" destroy-on-close>
			<el-form ref="formRef" :model="data.form" label-width="70px" style="padding: 20px">
				<el-row type="flex">
					<el-col :span="12">
						<template v-if="data.openAes">
							<el-form-item prop="file" label="分享文件">
								<el-upload :action="baseUrl + '/files/upload'" :headers="{ token: data.user.token }"
									:before-upload="beforeUploadFile" :limit="1">
									<el-button type="primary">上传</el-button>
								</el-upload>
							</el-form-item>
							<el-form-item v-if="data.form.fileName" label="已上传:">
								<div>{{ data.form.fileName }}</div>
							</el-form-item>
						</template>
						<template v-if="!data.openAes">
							<el-form-item prop="file" label="分享文件">
								<el-upload :action="baseUrl + '/files/upload'" :headers="{ token: data.user.token }"
									:on-success="handleFileSuccess" :before-upload="beforeUploadFile1" :limit="1">
									<el-button type="primary">上传</el-button>
								</el-upload>
							</el-form-item>
						</template>
					</el-col>
					<el-col :span="12">
						<el-switch v-model="data.openAes" active-text="加密" inactive-text="免密" active-color="#13ce66"
							inactive-color="#ff4949">
						</el-switch>
					</el-col>
				</el-row>
			</el-form>
			<template #footer>
				<span class="dialog-footer">
					<el-button @click="data.formVisible = false">取消</el-button>
					<el-button type="primary" @click="add">保存</el-button>
				</span>
			</template>
		</el-dialog>
	</div>
</template>

<script setup>
	import {
		reactive,
		onMounted,
		ref
	} from 'vue';
	import request from '@/utils/request';
	import {
		ElMessage,
		ElMessageBox
	} from 'element-plus';
	import CryptoJS from 'crypto-js';
	import JSEncrypt from 'jsencrypt';

	const baseUrl = import.meta.env.VITE_BASE_URL;

	const data = reactive({
		user: JSON.parse(localStorage.getItem('xm-user') || '{}'),
		tableData: [],
		formVisible: false,
		publicKeyVisible: false, // 新增字段控制公钥对话框的可见性
		selectedPublicKey: '', // 存储选中的公钥
		openAes: false, // 是否开启文件加密
		form: {
			currentSize: null,
			file: null,
			receiverId: null,
			fileName: '', // 新增字段存储文件名
			key: '', // 存储加密后的AES密钥
			iv: '', // 存储AES初始化向量
		},
		receiverPublicKey: '', // 新增字段存储接收者的公钥
	});

	const upload = ref(null);

	// 加载表格数据
	const load = () => {
		request.get('/friendList/selectAll', {
			params: {
				userId: data.user.id,
			},
		}).then((res) => {
			if (res.code === '200') {
				data.tableData = res.data;
			} else {
				ElMessage.error(res.msg);
			}
		});
	};

	// 显示公钥对话框
	const getPublicKey = async (row) => {
		try {
			// 获取接收者的公钥
			const publicKey = await fetchReceiverPublicKey(row.friendId);
			if (!publicKey) {
				ElMessage.error('无法获取接收者的公钥');
				return;
			}
			// data.selectedPublicKey =publicKey;
			// data.publicKeyVisible = true;
			// 下载公钥文件
			downloadPublicKey(publicKey, `${row.friendName}_public_key.txt`);
		} catch (error) {
			console.error('获取公钥时出错:', error);
			ElMessage.error('获取公钥时出错，请稍后再试');
		}

	};
	// 下载公钥文件
	const downloadPublicKey = (publicKey, fileName) => {
		const blob = new Blob([publicKey], {
			type: 'text/plain'
		});
		const url = window.URL.createObjectURL(blob);
		const a = document.createElement('a');
		a.href = url;
		a.download = fileName;
		document.body.appendChild(a);
		a.click();
		window.URL.revokeObjectURL(url);
		document.body.removeChild(a);
	};

	const showPublicKey = (row) => {
		console.log('friendId:' + row.friendId);
		request.get('/friendList/showPK', {
			params: {
				userId: data.user.id,
				friendId: row.friendId
			},
		}).then((res) => {
			if (res.code === '200') {
				ElMessage.success("发送成功");
			} else {
				ElMessage.error(res.msg);
			}
		});
	};

	// 打开编辑弹窗
	const showFriendApply = async (row) => {
		console.log('222222222:' + row);
		data.form.receiverId = row.friendId;

		try {
			// 获取接收者的公钥
			const publicKey = await fetchReceiverPublicKey(row.friendId);
			if (!publicKey) {
				ElMessage.error('无法获取接收者的公钥');
				return;
			}

			// 存储公钥到 data 对象中
			data.receiverPublicKey = publicKey;

			// 显示弹窗
			data.formVisible = true;
		} catch (error) {
			console.error('获取公钥时出错:', error);
			ElMessage.error('获取公钥时出错，请稍后再试');
		}
	};

	// 新增
	const add = () => {
		const payload = {
			aesKey: data.form.key,
			iv: data.form.iv,
			receiverId: data.form.receiverId,
			fileName: data.form.fileName,
			currentSize: data.form.currentSize,
			file: data.form.file,
			fileType: data.form.fileType, // 添加文件类型
		};

		request.post('/shareFile/add', payload).then((res) => {
			if (res.code === '200') {
				ElMessage.success('操作成功');
				data.formVisible = false;
				load();
			} else {
				ElMessage.error(res.msg);
			}
		}).catch((err) => {
			console.error('保存文件时出错:', err);
			ElMessage.error('保存文件时出错，请稍后再试');
		});
	};

	// 文件上传前检查
	const beforeUploadFile = async (file) => {
		let fileSize = file.size / 1024 / 1024;
		data.form.currentSize = fileSize;

		if (fileSize > 50) {
			ElMessage.error('文件太大，请选择小于50MB的文件');
			return false;
		}

		try {
			console.log('User:', data.user);

			const receiverPublicKey = data.receiverPublicKey;
			if (!receiverPublicKey) {
				ElMessage.error('无法获取接收者的公钥');
				return false;
			}

			const aesKey = CryptoJS.lib.WordArray.random(32);
			const iv = CryptoJS.lib.WordArray.random(16);

			const encryptedFile = await encryptFileWithAES(file, aesKey, iv);

			const encryptedAesKey = rsaEncrypt(aesKey.toString(CryptoJS.enc.Base64), receiverPublicKey);
			console.log('receiverPublicKey公钥:' + receiverPublicKey);
			console.log('使用RSA公钥加密AES密钥:' + encryptedAesKey);
			console.log('aesKey.toStringffffff:' + aesKey.toString(CryptoJS.enc.Base64));

			const formData = new FormData();
			formData.append('file', new Blob([encryptedFile], {
				type: file.type
			}));
			formData.append('key', encryptedAesKey);
			formData.append('iv', iv.toString(CryptoJS.enc.Base64));

			data.form.fileName = file.name;
			data.form.fileType = file.type;

			const response = await fetch(`${baseUrl}/files/upload`, {
				method: 'POST',
				headers: {
					token: data.user.token
				},
				body: formData,
			});

			if (!response.ok) {
				throw new Error('网络响应不正常');
			}
			const result = await response.json();
			console.log(result);
			data.form.file = result.data;

			data.form.key = encryptedAesKey;
			data.form.iv = iv.toString(CryptoJS.enc.Base64);
			return false;
		} catch (error) {
			console.error('上传文件时出错:', error);
			return false;
		}
	};

	// 提交上传
	const submitUpload = () => {
		upload.value.submit();
	};

	// 获取接收者的公钥
	const fetchReceiverPublicKey = async (id) => {
		try {
			const response = await fetch(`${baseUrl}/user/selectById/${id}`, {
				headers: {
					token: `${data.user.token}`,
				},
			});
			if (!response.ok) {
				throw new Error('无法获取公钥');
			}

			const responseData = await response.json();
			const publicKey = responseData.data.publicKey;
			console.log('公钥是：：：：：：' + publicKey);
			return publicKey;
		} catch (error) {
			console.error('获取公钥时出错:', error);
			return null;
		}
	};

	// AES加密文件
	const encryptFileWithAES = (file, aesKey, iv) => {
		return new Promise((resolve, reject) => {
			const reader = new FileReader();
			reader.onload = () => {
				try {
					const arrayBuffer = reader.result;
					const wordArray = CryptoJS.lib.WordArray.create(new Uint8Array(arrayBuffer));

					const encrypted = CryptoJS.AES.encrypt(wordArray, aesKey, {
						iv: iv,
						mode: CryptoJS.mode.CBC,
						padding: CryptoJS.pad.Pkcs7,
					});

					const ciphertextWords = encrypted.ciphertext.words;
					const ciphertextBytes = [];
					for (let i = 0; i < ciphertextWords.length; i++) {
						const hex = (ciphertextWords[i] >>> 0).toString(16).padStart(8, '0');
						ciphertextBytes.push(...hex.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));
					}
					resolve(new Uint8Array(ciphertextBytes));
				} catch (error) {
					reject(error);
				}
			};
			reader.onerror = reject;
			reader.readAsArrayBuffer(file);
		});
	};

	// RSA加密字符串
	const rsaEncrypt = (plainText, publicKeyPem) => {
		console.log('RSA加密字符串');
		const jsencrypt = new JSEncrypt();
		jsencrypt.setPublicKey(publicKeyPem);
		const encrypted = jsencrypt.encrypt(plainText);
		return encrypted;
	};

	// 文件上传成功的回调
	const handleFileSuccess = (response) => {
		console.log('上传成功的回调' + response.data);
		data.form.file = response.data;
	};

	const beforeUploadFile1 = (file) => {
		let fileSize = file.size / 1024 / 1024;
		data.form.currentSize = fileSize;
	};

	// 页面加载时执行
	onMounted(() => {
		load();
	});
</script>